Introduce gtk_render_insertion_cursor
authorPaolo Borelli <pborelli@gnome.org>
Sun, 27 Nov 2011 15:38:04 +0000 (16:38 +0100)
committerPaolo Borelli <pborelli@gnome.org>
Thu, 1 Dec 2011 00:22:39 +0000 (01:22 +0100)
The new function provides an API that takes the PangoLayout and index
as input params, this way it handles strong and weak cursors internally
factoring out all code duplicated in the widgets that need to render
cursors.

https://bugzilla.gnome.org/show_bug.cgi?id=640317

docs/reference/gtk/gtk3-sections.txt
gtk/gtk.symbols
gtk/gtkentry.c
gtk/gtklabel.c
gtk/gtkstylecontext.c
gtk/gtkstylecontext.h
gtk/gtktextdisplay.c
gtk/gtktextview.c

index d843e1228341df9ad7f9785dd4cf4c95150597e1..477bb18d203d849bccd4f5bcceb35685cab9a5b2 100644 (file)
@@ -5738,6 +5738,7 @@ gtk_render_slider
 gtk_render_activity
 gtk_render_icon_pixbuf
 gtk_render_icon
+gtk_render_insertion_cursor
 
 <SUBSECTION Standard>
 GTK_TYPE_STYLE_CONTEXT
index eca4605ae7af3d57f61ca6008548eca801ee3232..b310ae4fec7a06729c1770f689d2d0a57f19837b 100644 (file)
@@ -2274,6 +2274,7 @@ gtk_render_frame_gap
 gtk_render_handle
 gtk_render_icon
 gtk_render_icon_pixbuf
+gtk_render_insertion_cursor
 gtk_render_layout
 gtk_render_line
 gtk_render_option
index c0d8fb2deec5fd2c68074cb5f3776d64e3c567aa..9c41e0eb5e8c5c6b55493475cb4f7adce9bdff8c 100644 (file)
@@ -5848,29 +5848,20 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
 {
   GtkEntryPrivate *priv = entry->priv;
   GtkWidget *widget = GTK_WIDGET (entry);
-  GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
-  PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
-  GdkRectangle cursor_location;
-  gboolean split_cursor;
+  GtkStyleContext *context;
   PangoRectangle cursor_rect;
-  GtkBorder inner_border;
-  gint xoffset;
-  gint text_area_height;
   gint cursor_index;
   gboolean block;
   gboolean block_at_line_end;
   PangoLayout *layout;
   const char *text;
 
-  _gtk_entry_effective_inner_border (entry, &inner_border);
-
-  xoffset = inner_border.left - priv->scroll_offset;
-
-  text_area_height = gdk_window_get_height (priv->text_area);
+  context = gtk_widget_get_style_context (widget);
 
   layout = gtk_entry_ensure_layout (entry, TRUE);
   text = pango_layout_get_text (layout);
   cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos + priv->preedit_cursor) - text;
+
   if (!priv->overwrite_mode)
     block = FALSE;
   else
@@ -5879,58 +5870,16 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
 
   if (!block)
     {
-      gint strong_x, weak_x;
-      GtkTextDirection dir1, dir2;
-      gint x1 = 0;
-      gint x2 = 0;
-
-      gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
-
-      g_object_get (gtk_widget_get_settings (widget),
-                    "gtk-split-cursor", &split_cursor,
-                    NULL);
-
-      dir1 = (priv->resolved_dir == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-      dir2 = GTK_TEXT_DIR_NONE;
-
-      if (split_cursor)
-        {
-          x1 = strong_x;
-
-          if (weak_x != strong_x)
-            {
-              dir2 = (priv->resolved_dir == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
-              x2 = weak_x;
-            }
-        }
-      else
-        {
-          if (keymap_direction == priv->resolved_dir)
-            x1 = strong_x;
-          else
-            x1 = weak_x;
-        }
-
-      cursor_location.x = xoffset + x1;
-      cursor_location.y = inner_border.top;
-      cursor_location.width = 0;
-      cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
+      GtkBorder inner_border;
 
-      gtk_draw_insertion_cursor (widget, cr,
-                                 &cursor_location, TRUE, dir1,
-                                 dir2 != GTK_TEXT_DIR_NONE);
+      _gtk_entry_effective_inner_border (entry, &inner_border);
 
-      if (dir2 != GTK_TEXT_DIR_NONE)
-        {
-          cursor_location.x = xoffset + x2;
-          gtk_draw_insertion_cursor (widget, cr,
-                                     &cursor_location, FALSE, dir2,
-                                     TRUE);
-        }
+      gtk_render_insertion_cursor (context, cr,
+                                   inner_border.left - priv->scroll_offset, inner_border.top,
+                                   layout, cursor_index, priv->resolved_dir);
     }
   else /* overwrite_mode */
     {
-      GtkStyleContext *context;
       GdkRGBA cursor_color;
       GdkRectangle rect;
       gint x, y;
@@ -5944,8 +5893,6 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
       rect.width = PANGO_PIXELS (cursor_rect.width);
       rect.height = PANGO_PIXELS (cursor_rect.height);
 
-      context = gtk_widget_get_style_context (widget);
-
       _gtk_style_context_get_cursor_color (context, &cursor_color, NULL);
       gdk_cairo_set_source_rgba (cr, &cursor_color);
       gdk_cairo_rectangle (cr, &rect);
index aa55e74e38135d1c03231554883c9bdda735af93..8a8943a995bbff0d116a916b5e012e2a72a01dd5 100644 (file)
@@ -3978,84 +3978,6 @@ get_cursor_direction (GtkLabel *label)
   return PANGO_DIRECTION_LTR;
 }
 
-static void
-gtk_label_draw_cursor (GtkLabel  *label, cairo_t *cr, gint xoffset, gint yoffset)
-{
-  GtkLabelPrivate *priv = label->priv;
-  GtkWidget *widget;
-
-  if (priv->select_info == NULL)
-    return;
-
-  widget = GTK_WIDGET (label);
-  
-  if (gtk_widget_is_drawable (widget))
-    {
-      PangoDirection keymap_direction;
-      PangoDirection cursor_direction;
-      PangoRectangle strong_pos, weak_pos;
-      GtkTextDirection dir1, dir2;
-      gboolean split_cursor;
-      PangoRectangle *cursor1 = NULL;
-      PangoRectangle *cursor2 = NULL;
-      GdkRectangle cursor_location;
-
-      keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (widget)));
-      cursor_direction = get_cursor_direction (label);
-
-      gtk_label_ensure_layout (label);
-      
-      pango_layout_get_cursor_pos (priv->layout, priv->select_info->selection_end,
-                                  &strong_pos, &weak_pos);
-
-      g_object_get (gtk_widget_get_settings (widget),
-                   "gtk-split-cursor", &split_cursor,
-                   NULL);
-
-      dir1 = (cursor_direction == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-      dir2 = GTK_TEXT_DIR_NONE;
-
-      if (split_cursor)
-       {
-         cursor1 = &strong_pos;
-
-         if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
-           {
-              dir2 = (cursor_direction == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
-             cursor2 = &weak_pos;
-           }
-       }
-      else
-       {
-         if (keymap_direction == cursor_direction)
-           cursor1 = &strong_pos;
-         else
-           cursor1 = &weak_pos;
-       }
-
-      cursor_location.x = xoffset + PANGO_PIXELS (cursor1->x);
-      cursor_location.y = yoffset + PANGO_PIXELS (cursor1->y);
-      cursor_location.width = 0;
-      cursor_location.height = PANGO_PIXELS (cursor1->height);
-
-      gtk_draw_insertion_cursor (widget, cr,
-                                 &cursor_location, TRUE, dir1,
-                                 dir2 != GTK_TEXT_DIR_NONE);
-
-      if (dir2 != GTK_TEXT_DIR_NONE)
-       {
-         cursor_location.x = xoffset + PANGO_PIXELS (cursor2->x);
-         cursor_location.y = yoffset + PANGO_PIXELS (cursor2->y);
-         cursor_location.width = 0;
-         cursor_location.height = PANGO_PIXELS (cursor2->height);
-
-          gtk_draw_insertion_cursor (widget, cr,
-                                     &cursor_location, FALSE, dir2,
-                                     TRUE);
-       }
-    }
-}
-
 static GtkLabelLink *
 gtk_label_get_focus_link (GtkLabel *label)
 {
@@ -4167,8 +4089,18 @@ gtk_label_draw (GtkWidget *widget,
           GdkColor *link_color;
           GdkColor *visited_link_color;
 
-          if (info->selectable && gtk_widget_has_focus (widget))
-            gtk_label_draw_cursor (label, cr, x, y);
+          if (info->selectable &&
+              gtk_widget_has_focus (widget) &&
+              gtk_widget_is_drawable (widget))
+            {
+              PangoDirection cursor_direction;
+
+              cursor_direction = get_cursor_direction (label);
+              gtk_render_insertion_cursor (context, cr,
+                                           x, y,
+                                           priv->layout, priv->select_info->selection_end,
+                                           cursor_direction);
+            }
 
           focus_link = gtk_label_get_focus_link (label);
           active_link = info->active_link;
index 82cec95d81b3a3f81977620aa55bd49dfc769c6e..9711d038acadac9dd16aff70a96459d9134ad640 100644 (file)
@@ -4350,45 +4350,24 @@ gtk_render_icon (GtkStyleContext *context,
   cairo_restore (cr);
 }
 
-/**
- * gtk_draw_insertion_cursor:
- * @widget:  a #GtkWidget
- * @cr: cairo context to draw to
- * @location: location where to draw the cursor (@location->width is ignored)
- * @is_primary: if the cursor should be the primary cursor color.
- * @direction: whether the cursor is left-to-right or
- *             right-to-left. Should never be #GTK_TEXT_DIR_NONE
- * @draw_arrow: %TRUE to draw a directional arrow on the
- *        cursor. Should be %FALSE unless the cursor is split.
- *
- * Draws a text caret on @cr at @location. This is not a style function
- * but merely a convenience function for drawing the standard cursor shape.
- *
- * Since: 3.0
- */
-void
-gtk_draw_insertion_cursor (GtkWidget          *widget,
-                           cairo_t            *cr,
-                           const GdkRectangle *location,
-                           gboolean            is_primary,
-                           GtkTextDirection    direction,
-                           gboolean            draw_arrow)
+static void
+draw_insertion_cursor (GtkStyleContext *context,
+                       cairo_t         *cr,
+                       gdouble          x,
+                       gdouble          y,
+                       gdouble          height,
+                       gboolean         is_primary,
+                       PangoDirection   direction,
+                       gboolean         draw_arrow)
+
 {
-  gint stem_width;
-  gint arrow_width;
-  gint x, y;
-  gfloat cursor_aspect_ratio;
-  gint offset;
-  GtkStyleContext *context;
   GdkRGBA primary_color;
   GdkRGBA secondary_color;
+  gfloat cursor_aspect_ratio;
+  gint stem_width;
+  gint offset;
 
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (cr != NULL);
-  g_return_if_fail (location != NULL);
-  g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
-
-  context = gtk_widget_get_style_context (widget);
+  cairo_save (cr);
 
   _gtk_style_context_get_cursor_color (context, &primary_color, &secondary_color);
   gdk_cairo_set_source_rgba (cr, is_primary ? &primary_color : &secondary_color);
@@ -4401,43 +4380,176 @@ gtk_draw_insertion_cursor (GtkWidget          *widget,
                                "cursor-aspect-ratio", &cursor_aspect_ratio,
                                NULL);
 
-  stem_width = location->height * cursor_aspect_ratio + 1;
-  arrow_width = stem_width + 1;
+  stem_width = height * cursor_aspect_ratio + 1;
 
   /* put (stem_width % 2) on the proper side of the cursor */
-  if (direction == GTK_TEXT_DIR_LTR)
+  if (direction == PANGO_DIRECTION_LTR)
     offset = stem_width / 2;
   else
     offset = stem_width - stem_width / 2;
 
-  cairo_rectangle (cr,
-                   location->x - offset, location->y,
-                   stem_width, location->height);
+  cairo_rectangle (cr, x - offset, y, stem_width, height);
   cairo_fill (cr);
 
   if (draw_arrow)
     {
-      if (direction == GTK_TEXT_DIR_RTL)
+      gint arrow_width;
+      gint ax, ay;
+
+      arrow_width = stem_width + 1;
+
+      if (direction == PANGO_DIRECTION_RTL)
         {
-          x = location->x - offset - 1;
-          y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
+          ax = x - offset - 1;
+          ay = y + height - arrow_width * 2 - arrow_width + 1;
 
-          cairo_move_to (cr, x, y + 1);
-          cairo_line_to (cr, x - arrow_width, y + arrow_width);
-          cairo_line_to (cr, x, y + 2 * arrow_width);
+          cairo_move_to (cr, ax, ay + 1);
+          cairo_line_to (cr, ax - arrow_width, ay + arrow_width);
+          cairo_line_to (cr, ax, ay + 2 * arrow_width);
           cairo_fill (cr);
         }
-      else if (direction == GTK_TEXT_DIR_LTR)
+      else if (direction == PANGO_DIRECTION_LTR)
         {
-          x = location->x + stem_width - offset;
-          y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
+          ax = x + stem_width - offset;
+          ay = y + height - arrow_width * 2 - arrow_width + 1;
 
-          cairo_move_to (cr, x, y + 1);
-          cairo_line_to (cr, x + arrow_width, y + arrow_width);
-          cairo_line_to (cr, x, y + 2 * arrow_width);
+          cairo_move_to (cr, ax, ay + 1);
+          cairo_line_to (cr, ax + arrow_width, ay + arrow_width);
+          cairo_line_to (cr, ax, ay + 2 * arrow_width);
           cairo_fill (cr);
         }
+      else
+        g_assert_not_reached();
     }
+
+  cairo_restore (cr);
+}
+
+/**
+ * gtk_render_insertion_cursor:
+ * @context: a #GtkStyleContext
+ * @cr: a #cairo_t
+ * @x: X origin
+ * @y: Y origin
+ * @layout: the #PangoLayout of the text
+ * @index: the index in the #PangoLayout
+ * @direction: the #PangoDirection of the text
+ *
+ * Draws a text caret on @cr at the specified index of @layout.
+ *
+ * Since: 3.4
+ **/
+void
+gtk_render_insertion_cursor (GtkStyleContext *context,
+                             cairo_t         *cr,
+                             gdouble          x,
+                             gdouble          y,
+                             PangoLayout     *layout,
+                             int              index,
+                             PangoDirection   direction)
+{
+  GtkStyleContextPrivate *priv;
+  gboolean split_cursor;
+  PangoRectangle strong_pos, weak_pos;
+  PangoRectangle *cursor1, *cursor2;
+  PangoDirection keymap_direction;
+  PangoDirection direction2;
+
+  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
+  g_return_if_fail (index >= 0);
+
+  priv = context->priv;
+
+  g_object_get (gtk_settings_get_for_screen (priv->screen),
+                "gtk-split-cursor", &split_cursor,
+                NULL);
+
+  keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gdk_screen_get_display (priv->screen)));
+
+  pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
+
+  direction2 = PANGO_DIRECTION_NEUTRAL;
+
+  if (split_cursor)
+    {
+      cursor1 = &strong_pos;
+
+      if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
+        {
+          direction2 = (direction == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+          cursor2 = &weak_pos;
+        }
+    }
+  else
+    {
+      if (keymap_direction == direction)
+        cursor1 = &strong_pos;
+      else
+        cursor1 = &weak_pos;
+    }
+
+  draw_insertion_cursor (context,
+                         cr,
+                         x + PANGO_PIXELS (cursor1->x),
+                         y + PANGO_PIXELS (cursor1->y),
+                         PANGO_PIXELS (cursor1->height),
+                         TRUE,
+                         direction,
+                         direction2 != PANGO_DIRECTION_NEUTRAL);
+
+  if (direction2 != PANGO_DIRECTION_NEUTRAL)
+    {
+      draw_insertion_cursor (context,
+                             cr,
+                             x + PANGO_PIXELS (cursor2->x),
+                             y + PANGO_PIXELS (cursor2->y),
+                             PANGO_PIXELS (cursor2->height),
+                             FALSE,
+                             direction2,
+                             TRUE);
+    }
+}
+
+/**
+ * gtk_draw_insertion_cursor:
+ * @widget:  a #GtkWidget
+ * @cr: cairo context to draw to
+ * @location: location where to draw the cursor (@location->width is ignored)
+ * @is_primary: if the cursor should be the primary cursor color.
+ * @direction: whether the cursor is left-to-right or
+ *             right-to-left. Should never be #GTK_TEXT_DIR_NONE
+ * @draw_arrow: %TRUE to draw a directional arrow on the
+ *        cursor. Should be %FALSE unless the cursor is split.
+ *
+ * Draws a text caret on @cr at @location. This is not a style function
+ * but merely a convenience function for drawing the standard cursor shape.
+ *
+ * Since: 3.0
+ */
+void
+gtk_draw_insertion_cursor (GtkWidget          *widget,
+                           cairo_t            *cr,
+                           const GdkRectangle *location,
+                           gboolean            is_primary,
+                           GtkTextDirection    direction,
+                           gboolean            draw_arrow)
+{
+  GtkStyleContext *context;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (location != NULL);
+  g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
+
+  context = gtk_widget_get_style_context (widget);
+
+  draw_insertion_cursor (context, cr,
+                         location->x, location->y, location->height,
+                         is_primary,
+                         (direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR,
+                         draw_arrow);
 }
 
 static AtkAttributeSet *
index 30994fac9720a551fc45e592bb9a306ea3247777..547d45edd6324263c9a992761fb8e641ff5be7a5 100644 (file)
@@ -922,6 +922,14 @@ void        gtk_render_icon        (GtkStyleContext     *context,
                                     GdkPixbuf           *pixbuf,
                                     gdouble              x,
                                     gdouble              y);
+void        gtk_render_insertion_cursor
+                                   (GtkStyleContext     *context,
+                                    cairo_t             *cr,
+                                    gdouble              x,
+                                    gdouble              y,
+                                    PangoLayout         *layout,
+                                    int                  index,
+                                    PangoDirection       direction);
 
 void   gtk_draw_insertion_cursor    (GtkWidget          *widget,
                                      cairo_t            *cr,
index dad8e40d4ba6283341d80138625f7d571a4bef97..cda28144b09dbf612965747477f88c7f2952f261 100644 (file)
@@ -821,6 +821,7 @@ gtk_text_layout_draw (GtkTextLayout *layout,
                       cairo_t *cr,
                       GList **widgets)
 {
+  GtkStyleContext *context;
   gint offset_y;
   GtkTextRenderer *text_renderer;
   GtkTextIter selection_start, selection_end;
@@ -838,6 +839,8 @@ gtk_text_layout_draw (GtkTextLayout *layout,
   if (!gdk_cairo_get_clip_rectangle (cr, &clip))
     return;
 
+  context = gtk_widget_get_style_context (widget);
+
   line_list = gtk_text_layout_get_lines (layout, clip.y, clip.y + clip.height, &offset_y);
 
   if (line_list == NULL)
@@ -911,63 +914,17 @@ gtk_text_layout_draw (GtkTextLayout *layout,
               for (i = 0; i < line_display->cursors->len; i++)
                 {
                   int index;
-                  PangoRectangle strong_pos, weak_pos;
-                  PangoRectangle *cursor1, *cursor2;
-                  gboolean split_cursor;
-                  GtkTextDirection dir1, dir2;
-                  GdkRectangle cursor_location;
+                  PangoDirection dir;
 
                   index = g_array_index(line_display->cursors, int, i);
-                  pango_layout_get_cursor_pos (line_display->layout, index, &strong_pos, &weak_pos);
-
-                  dir1 = line_display->direction;
-                  dir2 = GTK_TEXT_DIR_NONE;
-
-                  g_object_get (gtk_widget_get_settings (widget),
-                                "gtk-split-cursor", &split_cursor,
-                                NULL);
-
-                  if (split_cursor)
-                    {
-                      cursor1 = &strong_pos;
-                      if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
-                        {
-                          dir2 = (line_display->direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
-                          cursor2 = &weak_pos;
-                        }
-                    }
-                  else
-                    {
-                      if (layout->keyboard_direction == line_display->direction)
-                        cursor1 = &strong_pos;
-                      else
-                        cursor1 = &weak_pos;
-                    }
-
-                  cursor_location.x = line_display->x_offset + PANGO_PIXELS (cursor1->x);
-                  cursor_location.y = line_display->top_margin + PANGO_PIXELS (cursor1->y);
-                  cursor_location.width = 0;
-                  cursor_location.height = PANGO_PIXELS (cursor1->height);
-
-                  gtk_draw_insertion_cursor (widget, cr,
-                                             &cursor_location, TRUE, dir1,
-                                             dir2 != GTK_TEXT_DIR_NONE);
-
-                  if (dir2 != GTK_TEXT_DIR_NONE)
-                    {
-                      cursor_location.x = line_display->x_offset + PANGO_PIXELS (cursor2->x);
-                      cursor_location.y = line_display->top_margin + PANGO_PIXELS (cursor2->y);
-                      cursor_location.width = 0;
-                      cursor_location.height = PANGO_PIXELS (cursor2->height);
-
-                      gtk_draw_insertion_cursor (widget, cr,
-                                                 &cursor_location, FALSE, dir2,
-                                                 TRUE);
-                    }
+                  dir = (line_display->direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+                  gtk_render_insertion_cursor (context, cr,
+                                               line_display->x_offset, line_display->top_margin,
+                                               line_display->layout, index, dir);
                 }
             }
         } /* line_display->height > 0 */
-          
+
       cairo_translate (cr, 0, line_display->height);
       gtk_text_layout_free_line_display (layout, line_display);
       
index 585c2a5fc5d420edf7d5a4768943da068c358d47..0c122582c061ed5f3a688687119f7168fae8273c 100644 (file)
@@ -8622,7 +8622,7 @@ text_window_invalidate_cursors (GtkTextWindow *win)
   gtk_text_layout_get_cursor_locations (priv->layout, &iter,
                                         &strong, &weak);
 
-  /* cursor width calculation as in gtkstyle.c:draw_insertion_cursor(),
+  /* cursor width calculation as in gtkstylecontext.c:draw_insertion_cursor(),
    * ignoring the text direction be exposing both sides of the cursor
    */